import math
from framebuf import FrameBuffer, MONO_HLSB

class Display:
    def __init__(self, oled):
        self.oled = oled
        self.height = oled.height  # 获取屏幕高度
        
        # 根据屏幕高度选择显示模式
        if self.height == 32:
            # 128x32 显示参数
            self.meter_x = 8          # 表盘起始x坐标
            self.meter_y = 4          # 表盘起始y坐标
            self.meter_width = 80     # 表盘宽度
            self.meter_height = 24    # 表盘高度
            self.value_x = 96         # 数值显示x坐标
            self.value_y = 12         # 数值显示y坐标
            self.status_x = 120       # 状态点x坐标
            self.status_y = 4         # 状态点y坐标
            self.step_width = 4       # 阶梯宽度
        else:
            # 128x64 显示参数
            self.center_x = 64        # 圆心x坐标（屏幕中心）
            self.center_y = 100       # 圆心y坐标
            self.radius = 85          # 圆弧半径
            self.value_x = 96         # 数值显示位置
            self.value_y = 45         # 数值显示y坐标
            self.status_x = 120       # 状态点位置
            self.status_y = 4
            self.pointer_width = 4    # 指针宽度
            self.start_angle = 135    # 起始角度（指针起点）
            self.end_angle = 45       # 结束角度（指针终点）
            # 装饰弧参数
            self.dec_start_angle = 160  # 装饰弧起始角度
            self.dec_end_angle = 20     # 装饰弧结束角度
            self.text_y = 52           # 文字显示y坐标
            # 根据文字位置计算装饰弧半径
            text_height = 8            # 文字高度（像素）
            arc_margin = 3             # 弧形与文字的边距
            self.dec_radius = (self.center_y - self.text_y - text_height - arc_margin) / math.sin(math.radians(self.dec_start_angle - 90))
            
    def update_meter(self, value, status_on=True):
        self.oled.fill(0)  # 清空显示
        
        if self.height == 32:
            self._draw_bar_meter(value)
        else:
            self._draw_dial_meter(value)
            
        # 显示数值
        self._draw_value(value)
        
        # 显示状态点
        self._draw_status(status_on)
        
        # 更新显示
        self.oled.show()
        
    def _draw_bar_meter(self, value):
        # 绘制刻度
        for i in range(6):
            x = self.meter_x + (self.meter_width - 4) * i // 5
            # 主刻度线
            self.oled.line(x, 
                          self.meter_y + self.meter_height//2 + 2,
                          x, 
                          self.meter_y + self.meter_height - 2, 
                          1)
            
            # 小刻度线
            if i < 5:
                mid_x = x + (self.meter_width - 4) // 10
                self.oled.line(mid_x, 
                             self.meter_y + self.meter_height*2//3 + 2,
                             mid_x, 
                             self.meter_y + self.meter_height - 4, 
                             1)
        
        # 绘制进度条
        total_width = int((value * (self.meter_width - 4)) / 1024)
        bar_start_x = self.meter_x
        for x in range(bar_start_x, bar_start_x + total_width, self.step_width):
            step_width = min(self.step_width - 1, 
                           bar_start_x + total_width - x)
            self.oled.fill_rect(x,
                              self.meter_y + 2,
                              step_width,
                              self.meter_height//2 - 2,
                              1)
                              
    def _draw_dial_meter(self, value):
        # 先绘制装饰弧
        for angle in range(self.dec_end_angle, self.dec_start_angle + 1, 2):
            rad = math.radians(angle)
            x = int(self.center_x + self.dec_radius * math.cos(rad))
            y = int(self.center_y - self.dec_radius * math.sin(rad))
            if 0 <= y < self.height:
                self.oled.pixel(x, y, 1)
        
        # 绘制圆弧
        for angle in range(self.end_angle, self.start_angle + 1, 2):
            rad = math.radians(angle)
            x = int(self.center_x + self.radius * math.cos(rad))
            y = int(self.center_y - self.radius * math.sin(rad))
            if 0 <= y < self.height:
                self.oled.pixel(x, y, 1)
            
        # 计算角度范围和刻度间隔
        angle_range = self.start_angle - self.end_angle
        major_divisions = 4  # 主刻度分隔数量
        minor_divisions = 8  # 次刻度分隔数量
        
        # 绘制主刻度线
        for i in range(major_divisions + 1):
            angle = self.start_angle - (angle_range * i) // major_divisions
            rad = math.radians(angle)
            
            # 主刻度线（较长）
            inner_x = int(self.center_x + (self.radius - 8) * math.cos(rad))
            inner_y = int(self.center_y - (self.radius - 8) * math.sin(rad))
            outer_x = int(self.center_x + (self.radius + 3) * math.cos(rad))
            outer_y = int(self.center_y - (self.radius + 3) * math.sin(rad))
            
            if 0 <= inner_y < self.height and 0 <= outer_y < self.height:
                self.oled.line(inner_x, inner_y, outer_x, outer_y, 1)
        
        # 绘制次刻度线
        for i in range(minor_divisions + 1):
            # 跳过与主刻度重合的位置
            if (i % 2) == 0:
                continue
                
            angle = self.start_angle - (angle_range * i) // minor_divisions
            rad = math.radians(angle)
            
            # 次刻度线（较短）
            inner_x = int(self.center_x + (self.radius - 4) * math.cos(rad))
            inner_y = int(self.center_y - (self.radius - 4) * math.sin(rad))
            outer_x = int(self.center_x + (self.radius + 1) * math.cos(rad))
            outer_y = int(self.center_y - (self.radius + 1) * math.sin(rad))
            
            if 0 <= inner_y < self.height and 0 <= outer_y < self.height:
                self.oled.line(inner_x, inner_y, outer_x, outer_y, 1)
        
        # 计算指针角度
        angle = math.radians(self.start_angle - (value * (self.start_angle - self.end_angle)) / 1024)
        
        # 绘制指针主体（单根线）
        end_x = int(self.center_x + self.radius * math.cos(angle))
        end_y = int(self.center_y - self.radius * math.sin(angle))
        start_x = int(self.center_x + (self.radius - 28) * math.cos(angle))  # 指针起点更远离刻度内侧
        start_y = int(self.center_y - (self.radius - 28) * math.sin(angle))
        
        # 只绘制在显示范围内的指针
        if 0 <= end_y < self.height and 0 <= start_y < self.height:
            # 绘制指针主体
            self.oled.line(start_x, start_y, end_x, end_y, 1)
            
            # 绘制指针两侧的短线，增加视觉效果
            side_length = 5  # 缩短侧边线长度
            angle_offset = math.pi / 2  # 90度偏移
            
            # 计算侧边短线的端点
            side1_x = start_x + int(side_length * math.cos(angle + angle_offset))
            side1_y = start_y - int(side_length * math.sin(angle + angle_offset))
            side2_x = start_x + int(side_length * math.cos(angle - angle_offset))
            side2_y = start_y - int(side_length * math.sin(angle - angle_offset))
            
            # 绘制侧边短线
            self.oled.line(start_x, start_y, side1_x, side1_y, 1)
            self.oled.line(start_x, start_y, side2_x, side2_y, 1)
            
        # 在装饰弧内显示文字
        text = "CPU%"  # 可以根据需要修改显示的文字
        # 计算文字起始位置，使其居中
        text_x = self.center_x - (len(text) * 8) // 2  # 假设字体宽度为8像素
        self.oled.text(text, text_x, self.text_y, 1)
        
    def _draw_value(self, value):
        """显示数值，将0-1000的值转换为百分比"""
        # 转换为百分比 (0-1000 -> 0-100)
        percent = value / 10.0
        
        # 格式化显示字符串
        value_str = f"{percent:.1f}"
        
        # 绘制数值框和文字
        self.oled.rect(self.value_x - 4, self.value_y - 4,
                      32, 16, 1)
        # 计算文本居中位置
        x = self.value_x + (24 - len(value_str) * 8) // 2
        self.oled.text(value_str, x, self.value_y, 1)
        
    def _draw_status(self, status_on):
        if status_on:
            self.oled.fill_rect(self.status_x, self.status_y, 2, 2, 1)
